' Stephen Toub
' Coded and published in January 2007 issue of MSDN Magazine 
' http://msdn.microsoft.com/msdnmag/issues/07/01/PreviewHandlers/default.aspx


Imports Microsoft.VisualBasic
Imports System
Imports System.IO
Imports System.Drawing
Imports System.Windows.Forms
Imports System.Collections.Generic
Imports System.Runtime.InteropServices
Imports C4F.DevKit.PreviewHandler.PreviewHandlerFramework

Namespace C4F.DevKit.PreviewHandler.PreviewHandlers
    Friend NotInheritable Class FileTypeIconProvider
        Implements IDisposable
        Private _icons As ImageList
        Private _extensionToIconIndex As Dictionary(Of String, Integer)

        Public Sub New()
            _icons = New ImageList()
            _extensionToIconIndex = New Dictionary(Of String, Integer)()
            _icons.Images.Add(My.Resources.TreeView_XP_Explorer_ParentNode) ' Folder index
        End Sub

        Public Sub Dispose() Implements IDisposable.Dispose
            If Not _icons Is Nothing Then
                _icons.Dispose()
                _icons = Nothing
            End If
        End Sub

        Public ReadOnly Property Icons() As ImageList
            Get
                Return _icons
            End Get
        End Property

        Public ReadOnly Property FolderIndex() As Integer
            Get
                Return 0
            End Get
        End Property

        Public Function GetIconIndexForFile(ByVal p As String) As Integer
            ' Get the extension.  This will work for either file paths or urls.
            If p Is Nothing Then
                Return -1
            End If
            Dim ext As String = Path.GetExtension(p.Trim())

            Dim index As Integer
            If (Not _extensionToIconIndex.TryGetValue(ext, index)) Then
                ' Get the icon for the file
                Dim shinfo As SHFILEINFO = New SHFILEINFO()
                Const SHGFI_ICON As UInteger = &H100, SHGFI_SMALLICON As UInteger = &H1, SHGFI_USEFILEATTRIBUTES As UInteger = &H10
                Dim rv As IntPtr = SHGetFileInfo(p, 0, shinfo, CUInt(Marshal.SizeOf(shinfo)), SHGFI_ICON Or SHGFI_SMALLICON Or SHGFI_USEFILEATTRIBUTES)
                If rv = IntPtr.Zero Then
                    Return -1
                End If

                ' The icon is returned in the hIcon member of the shinfo struct
                _icons.Images.Add(Icon.FromHandle(shinfo.hIcon))
                Dim pos As Integer = _icons.Images.Count - 1
                _extensionToIconIndex(ext) = pos
                index = pos
            End If

            ' Return the mapped index.
            Return index
        End Function

        Private Structure SHFILEINFO
            Public hIcon As IntPtr
            Public iIcon As IntPtr
            Public dwAttributes As UInteger
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)> _
            Public szDisplayName As String
            <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)> _
            Public szTypeName As String
        End Structure

        <DllImport("shell32.dll")> _
        Private Shared Function SHGetFileInfo(ByVal pszPath As String, ByVal dwFileAttributes As UInteger, ByRef psfi As SHFILEINFO, ByVal cbSizeFileInfo As UInteger, ByVal uFlags As UInteger) As IntPtr
        End Function
    End Class
End Namespace
